package com.openNetty.server.sftp;

import com.openNetty.server.nettyserver.Global;
import com.jcraft.jsch.*;

import java.io.*;
import java.util.*;

/**
 * @author zhenggm
 * @version 1.0.0
 */
public class SftpConnect {


    /**
     * Sftp
     */
    ChannelSftp sftp = null;
    /**
     * 主机
     */
    private String host = "";
    /**
     * 端口
     */
    private int port = 0;
    /**
     * 用户名
     */
    private String username = "";
    /**
     * 密码
     */
    private String password = "";

    private static SftpConnect sftpConnect = null;

    /**
     * 构造函数
     *
     * @param host     主机
     * @param port     端口
     * @param username 用户名
     * @param password 密码
     */
    public SftpConnect(String host, int port, String username,
                       String password) {

        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    public SftpConnect() {
    }

    public static SftpConnect getInstance() {
        if (sftpConnect == null) {
            sftpConnect = new SftpConnect(Global.properties.getProperty("sftp.address"),
                    Integer.parseInt(Global.properties.getProperty("sftp.port")),
                    Global.properties.getProperty("sftp.username"),
                    Global.properties.getProperty("sftp.password"));
        }
        return sftpConnect;
    }


    /**
     * 连接sftp服务器
     *
     * @throws Exception
     */
    public void connect() throws Exception {

        JSch jsch = new JSch();
        Session sshSession = jsch.getSession(this.username, this.host, this.port);

        sshSession.setPassword(password);
        Properties sshConfig = new Properties();
        sshConfig.put("StrictHostKeyChecking", "no");
        sshSession.setConfig(sshConfig);
        sshSession.connect(20000);

        Channel channel = sshSession.openChannel("sftp");
        channel.connect();
        this.sftp = (ChannelSftp) channel;
    }

    /**
     * Disconnect with server
     *
     * @throws Exception
     */
    public void disconnect() throws Exception {
        if (this.sftp != null) {
            if (this.sftp.isConnected()) {
                this.sftp.disconnect();
            } else if (this.sftp.isClosed()) {
            }
        }
    }

    /**
     * 上传单个文件
     *
     * @param directory  上传的目录
     * @param uploadFile 要上传的文件
     * @throws Exception
     */
    public void upload(String directory, String uploadFile) throws Exception {
        this.sftp.cd(directory);
        File file = new File(uploadFile);
        this.sftp.put(new FileInputStream(file), file.getName());
    }


    public void mkdir(String directory) {
        try {
            this.sftp.mkdir(directory);
        } catch (SftpException e) {
            e.printStackTrace();
        }
    }


    /**
     * 上传目录下全部文件
     *
     * @param directory 上传的目录
     * @throws Exception
     */
    public void uploadByDirectory(String directory) throws Exception {

        String uploadFile = "";
        List<String> uploadFileList = this.listFiles(directory);
        Iterator<String> it = uploadFileList.iterator();

        while (it.hasNext()) {
            uploadFile = it.next().toString();
            this.upload(directory, uploadFile);
        }
    }

    /**
     * 下载单个文件
     *
     * @param directory     下载目录
     * @param downloadFile  下载的文件
     * @param saveDirectory 存在本地的路径
     * @throws Exception
     */
    public void download(String directory, String downloadFile, String saveDirectory) throws Exception {
        try {
            if (!"mysql.sock".equals(downloadFile)) {
                String saveFile = saveDirectory + "//" + downloadFile;
                this.sftp.cd(directory);
                File file = new File(saveFile);
                this.sftp.get(downloadFile, new FileOutputStream(file));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载目录下全部文件
     *
     * @param directory     下载目录
     * @param saveDirectory 存在本地的路径
     * @throws Exception
     */
    public void downloadByDirectory(String directory, String saveDirectory) throws Exception {
        String downloadFile = "";
        List<String> downloadFileList = this.listFiles(directory);
        Iterator<String> it = downloadFileList.iterator();

        while (it.hasNext()) {
            downloadFile = it.next().toString();
            if (downloadFile.toString().indexOf(".") < 0) {
                continue;
            }
            this.download(directory, downloadFile, saveDirectory);
        }
    }

    public void downloadAllDirectory(String directory, String saveDirectory) throws Exception {
        String downloadFile = "";
        List<String> downloadFileList = this.listFiles(directory);
        Iterator<String> it = downloadFileList.iterator();

        while (it.hasNext()) {
            downloadFile = it.next().toString();
//            if (downloadFile.toString().indexOf(".") < 0) {
//                continue;
//            }
            try {
                String dir = directory + "/" + downloadFile;
                if (isDirExist(dir)) {
                    this.mkdirAndDownload(dir, downloadFile, saveDirectory);
                } else {
                    this.download(directory, downloadFile, saveDirectory);
                }
            } catch (Exception e) {
                if (e.getMessage().toLowerCase().equals("no such file")) {
                    continue;
                }
            }
        }
    }

    /**
     * @param dir
     * @param downloadFile
     * @param saveDirectory
     * @throws Exception
     */
    private void mkdirAndDownload(String dir, String downloadFile, String saveDirectory) throws Exception {
        String saveFile = saveDirectory + "/" + downloadFile;

        this.sftp.cd(dir);
        File file = new File(saveFile);
        if (!file.exists()) {
            file.mkdir();
        }
        downloadAllDirectory(dir, saveFile);
    }

    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     * @throws Exception
     */
    public void delete(String directory, String deleteFile) throws Exception {
        this.sftp.cd(directory);
        this.sftp.rm(deleteFile);
    }

    /**
     * 列出目录下的文件
     *
     * @param directory 要列出的目录
     * @return list 文件名列表
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public List<String> listFiles(String directory) throws Exception {

        Vector fileList;
        List<String> fileNameList = new ArrayList<String>();

        fileList = this.sftp.ls(directory);
        Iterator it = fileList.iterator();

        while (it.hasNext()) {
            String fileName = ((ChannelSftp.LsEntry) it.next()).getFilename();
            if (".".equals(fileName) || "..".equals(fileName)) {
                continue;
            }
            fileNameList.add(fileName);

        }

        return fileNameList;
    }

    /**
     * 更改文件名
     *
     * @param directory 文件所在目录
     * @param oldFileNm 原文件名
     * @param newFileNm 新文件名
     * @throws Exception
     */
    public void rename(String directory, String oldFileNm, String newFileNm) throws Exception {
        this.sftp.cd(directory);
        this.sftp.rename(oldFileNm, newFileNm);
    }

    public void cd(String directory) throws Exception {
        this.sftp.cd(directory);
    }

    public InputStream get(String directory) throws Exception {
        InputStream streatm = this.sftp.get(directory);
        return streatm;
    }

    public boolean isDirExist(String directory) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }

}
